package Project4;

import Project4.analysis.*;
import Project4.node.*;
import java.util.*;


class SymbolTableMethodSweep extends DepthFirstAdapter
{
    private String tempName;
    private String tempType;
    private SymbolTable symbolTable;
	private ArrayList<Variable> variableList = new ArrayList<Variable>();

	private boolean insideMethod = false;

 	public SymbolTableMethodSweep(SymbolTable table) {
        this.symbolTable = table;
	}
	
	/*
	* stmt stmtseq
	* stuff; things; ideas;
	*/
	public void caseAAStmtseq(AAStmtseq node){
		node.getStmt().apply(this);
		node.getStmtseq().apply(this);
	}

	public void caseADStmt(ADStmt node){
		//scope in
		this.symbolTable.AddBlockScope();
		node.getStmtseq().apply(this);
		//scope out
		this.symbolTable.RemoveBlockScope();
	}

	public void caseAEStmt(AEStmt node){
		//scope in
		this.symbolTable.AddBlockScope();
		node.getStmtseq().apply(this);
		//scope out
		this.symbolTable.RemoveBlockScope();
	}

	public void caseAFStmt(AFStmt node){
		//scope in
		this.symbolTable.AddBlockScope();
		node.getStmtseq().apply(this);
		//scope out
		this.symbolTable.RemoveBlockScope();
	}

	/*
	* switch lparen expr rparen lcurly case lparen int rparen colon stmtseq cases default colon stmtseq rcurly
	*
	*/
	public void caseALStmt(ALStmt node){
		//scope in
		this.symbolTable.AddBlockScope();
		node.getLf().apply(this);
		//scope out
		this.symbolTable.RemoveBlockScope();

		node.getCases().apply(this);

		this.symbolTable.AddBlockScope();
		node.getLh().apply(this);
		this.symbolTable.RemoveBlockScope();
	}

	public void caseAJStmt(AJStmt node){
		if(insideMethod){
			//ERROR: Declaring method inside method
			System.out.println("ERROR: Cannot declare method inside method");
		}
		else
		{
			insideMethod = true;
			tempType = "";
			node.getType().apply(this);
			tempName = node.getId().getText();

			Method m = new Method(tempName, tempType);

			variableList.clear();
			node.getVars().apply(this);

			for(Variable v: variableList){
				m.addParam(v);
				m.addVar(v);
			}
			
			this.symbolTable.AddMethod(m);
			node.getCurlystmtseq().apply(this);
			insideMethod = false;
		}
	}

	public void caseAACurlystmtseq(AACurlystmtseq node){
		node.getStmtseq().apply(this);
	}

	public void caseAACases(AACases node){
		this.symbolTable.AddBlockScope();
		node.getStmtseq().apply(this);
		this.symbolTable.RemoveBlockScope();

		node.getCases().apply(this);
	}

    public void caseAAVars(AAVars node){
        node.getVarlist().apply(this);
    }

    public void caseAAVarlist(AAVarlist node){
		node.getVarlist().apply(this);
		tempType = "";
		node.getType().apply(this);
		tempName = node.getId().getText();
		variableList.add(new Variable(tempName, tempType));
    }

    public void caseABVarlist(ABVarlist node){
        tempType = "";
		node.getType().apply(this);
		tempName = node.getId().getText();
		variableList.add(new Variable(tempName, tempType));
    }

    public void caseAAType(AAType node){
        tempType = "INT";
    }

    public void caseABType(ABType node){
        tempType = "REAL";
    }

    public void caseACType(ACType node){
        tempType = "STRING";
    }

    public void caseADType(ADType node){
        tempType = "BOOLEAN";
    }

    public void caseAEType(AEType node){
        tempType = "VOID";
    }

}
